<?php

// @formatter:off
/**
 * @file WCViewController.php
 *
 * @author Alejandro Dario Simi
 * @date $Date: 2014-06-03 03:40:32 +0000 (Tue, 03 Jun 2014) $
 *
 * $Id: WCViewController.php 112 2014-06-03 03:40:32Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/includes/mvc/WCViewController.php $
 */
// @formatter:on

abstract class WCViewController {
	const OutputFormatDump = "var_dump";
	const OutputFormatJSON = "json";
	const OutputFormatPrint = "print_r";
	const OutputFormatSerialized = "serialized";
	const OutputFormatSkin = "skin";
	const OutputFormatXML = "xml";
	//
	// Protected class properties.
	protected static $_DebugParameters = array(
		"format",
		"nolayout",
		"noaction",
		"expainsearch",
		"expaincache"
	);
	//
	// Protected properties.
	protected $_cacheTime = false;
	/**
	 * @var stdClass
	 */
	protected $_allowedParams = array();
	protected $_config = false;
	protected $_id = false;
	/**
	 * @var WCViewManager
	 */
	protected $_manager = false;
	protected $_name = false;
	protected $_outputFormat = self::OutputFormatJSON;
	protected $_parentView = false;
	protected $_postAllowedParams = array();
	protected $_postRequiredParams = array();
	protected $_requiredParams = array();
	protected $_selector = array();
	protected $_settings = array();
	protected $_skin = false;
	/**
	 * @var WCTranslate
	 */
	protected $_tr = false;
	//
	// Magic methods.
	public function __construct() {
		$this->_manager = WCViewManager::I();
		$this->_name = get_called_class();
	}
	//
	// Public methods.
	public function build() {
		$dataOutput = false;

		if($this->_cacheTime) {
			$dataOutput = $this->_manager->getCache($this->selector(), WCViewManager::CacheTypeHTML, $this->_config->cache->fullurl);
		}

		if($dataOutput === false) {
			$dataOutput = $this->subBuild();

			if($this->_cacheTime) {
				$this->_manager->saveCache($this->selector(), WCViewManager::CacheTypeHTML, $dataOutput, $this->_cacheTime, $this->_config->cache->fullurl);
			}
		}

		return $dataOutput;
	}
	public function check() {
		$check = WC_HTTPERROR_OK;

		if($this->_requiredParams) {
			foreach($this->_requiredParams as $param) {
				$ok = false;

				$list = array();
				if(!is_array($param)) {
					$list[] = $param;
				} else {
					$list = $param;
				}

				foreach($list as $p) {
					if(isset($_REQUEST[$p])) {
						$ok = true;
						break;
					}
				}
				if(!$ok) {
					global $errno;
					global $error;

					$check = WC_HTTPERROR_BAD_REQUEST;
					$errno = $check;
					$error = "Not all required url param where given. Checking params: ".implode(", ", $list);
					break;
				}
			}
		}
		if($this->_allowedParams) {
			$checkArray = array();
			foreach(array_merge($this->_allowedParams, $this->_requiredParams) as $list) {
				if(is_array($list)) {
					$checkArray = array_merge($checkArray, $list);
				} else {
					$checkArray[] = $list;
				}
			}
			$checkArray = array_unique(array_merge($checkArray, self::$_DebugParameters));

			foreach($_REQUEST as $param => $value) {
				if(!in_array($param, $checkArray)) {
					$check = WC_HTTPERROR_BAD_REQUEST;

					global $errno;
					global $error;

					$errno = WC_HTTPERROR_BAD_REQUEST;
					$error = "Url parameter '{$param}' not allowed";
					break;
				}
			}
		}

		if($this->_manager->isPost()) {
			if($this->_postRequiredParams) {
				foreach($this->_postRequiredParams as $param) {
					$ok = false;

					$list = array();
					if(!is_array($param)) {
						$list[] = $param;
					} else {
						$list = $param;
					}

					foreach($list as $p) {
						if(isset($_POST[$p])) {
							$ok = true;
							break;
						}
					}
					if(!$ok) {
						global $errno;
						global $error;

						$check = WC_HTTPERROR_BAD_REQUEST;
						$errno = $check;
						$error = "Not all required POST param where given. Checking params: ".implode(", ", $list);
						break;
					}
				}
			}
			if($this->_postAllowedParams) {
				$checkArray = array();
				foreach(array_merge($this->_postAllowedParams, $this->_postRequiredParams) as $list) {
					if(is_array($list)) {
						$checkArray = array_merge($checkArray, $list);
					} else {
						$checkArray[] = $list;
					}
				}
				$checkArray = array_unique(array_merge($checkArray, self::$_DebugParameters));

				foreach($_POST as $param => $value) {
					if(!in_array($param, $checkArray)) {
						$check = WC_HTTPERROR_BAD_REQUEST;

						global $errno;
						global $error;

						$errno = WC_HTTPERROR_BAD_REQUEST;
						$error = "Post parameter '{$param}' not allowed";
						break;
					}
				}
			}
		}

		return $check;
	}
	public function id() {
		return $this->_id;
	}
	public function name() {
		return $this->_name;
	}
	public function parentView() {
		return $this->_parentView;
	}
	public function outputFormat() {
		return $this->_outputFormat;
	}
	public function selector() {
		$this->_selector["format"] = $this->outputFormat();
		return $this->_selector;
	}
	public function run() {
		$ok = false;
		$isPost = $this->_manager->isPost();

		if($this->_cacheTime && !$isPost) {
			$settings = $this->_manager->getCache($this->selector(), WCViewManager::CacheTypeData, $this->_config->cache->fullurl);
			if($settings) {
				foreach($settings as $key => $value) {
					$this->_manager->$key = $value;
				}
				$ok = true;
			}
		}

		if($ok === false) {
			if($isPost && method_exists($this, "subRunPOST")) {
				$ok = $this->subRunPOST();
			} else {
				$ok = $this->subRun();
			}

			if($ok && $this->_cacheTime && !$isPost) {
				$this->_manager->saveCache($this->selector(), WCViewManager::CacheTypeData, $this->_manager->settings(), $this->_cacheTime, $this->_config->cache->fullurl);
			}
		}

		return $ok;
	}
	public function setConfig(stdClass $config) {
		$this->_config = $config;

		$this->setConfigCache();
		$this->setConfigParams();
	}
	public function setOutputFormat($format = self::OutputFormatJSON) {
		$this->_outputFormat = $format;
	}
	public function setParentView($parentView) {
		$this->_parentView = $parentView;
		return $this->parentView();
	}
	public function setSkin($skin) {
		if(is_readable($skin)) {
			$this->_skin = $skin;
			$this->setOutputFormat(self::OutputFormatSkin);
		}
	}
	public function tr($name, $keywords = false) {
		if(!$this->_tr) {
			$this->_tr = WCTranslate::I();
		}
		return $this->_tr->translate($name, $keywords);
	}
	//
	// Protected methods.
	protected function buildSkin() {
		global $wcPaths;

		$parser = new WCParser();
		$parser->templatesRoot("{$wcPaths["mvc"]["skins"]}/{$this->_manager->SKIN}");
		$parser->massiveAssign($this->_manager->settings(), true);
		$parser->massiveAssign($this->_manager->constants(), false);
		$parser->load($this->_skin, true);
		$parser->noWarnings();
		$parser->noSummary();

		return $parser->parse();
	}
	protected function setConfigCache() {
		if($this->_config->cache->duration && $this->_cacheTime) {
			$this->_config->cache->duration = $this->_cacheTime;
		}

		if($this->_config->cache->duration) {
			$this->_cacheTime = $this->_config->cache->duration;

			if(!$this->_config->cache->fullurl && in_array("group", $this->_config->cache->keys)) {
				global $wcGroup;
				$this->_selector["group"] = $wcGroup->id();
			}
			if(in_array("profile", $this->_config->cache->keys)) {
				global $wcProfile;
				$this->_selector["profile"] = $wcProfile->name();
			}
			if(!$this->_config->cache->fullurl && in_array("comic", $this->_config->cache->keys) || in_array("comic?", $this->_config->cache->keys)) {
				global $wcComic;
				if($wcComic && $wcComic->ok()) {
					$this->_selector["comic"] = $wcComic->id();
				} elseif(!in_array("comic?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("image", $this->_config->cache->keys) || in_array("image?", $this->_config->cache->keys)) {
				global $wcImage;
				if($wcImage && $wcImage->ok()) {
					$this->_selector["image"] = $wcImage->id();
				} elseif(!in_array("image?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("tag", $this->_config->cache->keys) || in_array("tag?", $this->_config->cache->keys)) {
				global $wcTag;
				if($wcTag && $wcTag->ok()) {
					$this->_selector["tag"] = $wcTag->id();
				} elseif(!in_array("tag?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("directory", $this->_config->cache->keys) || in_array("directory?", $this->_config->cache->keys)) {
				global $wcDirectory;
				if($wcDirectory && $wcDirectory->ok()) {
					$this->_selector["directory"] = $wcDirectory->id();
				} elseif(!in_array("directory?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("rule", $this->_config->cache->keys) || in_array("rule?", $this->_config->cache->keys)) {
				global $wcRule;
				if($wcRule && $wcRule->ok()) {
					$this->_selector["rule"] = $wcRule->id();
				} elseif(!in_array("rule?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("rule_action", $this->_config->cache->keys) || in_array("rule_action?", $this->_config->cache->keys)) {
				global $wcRuleAction;
				if($wcRuleAction && $wcRuleAction->ok()) {
					$this->_selector["rule_action"] = $wcRuleAction->id();
				} elseif(!in_array("rule_action?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("collection", $this->_config->cache->keys) || in_array("collection?", $this->_config->cache->keys)) {
				global $wcCollection;
				if($wcCollection && $wcCollection->ok()) {
					$this->_selector["collection"] = $wcCollection->id();
				} elseif(!in_array("collection?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(in_array("user", $this->_config->cache->keys) || in_array("user?", $this->_config->cache->keys)) {
				global $wcUser;

				if($wcUser && $wcUser->ok()) {
					$this->_selector["user"] = $wcUser->id();
				} elseif(!WCSessions::I()->isLogged()) {
					unset($this->_selector["user"]);
				} elseif(!in_array("user?", $this->_config->cache->keys)) {
					$this->_cacheTime = false;
				}
			}
			if(!$this->_config->cache->fullurl && in_array("page", $this->_config->cache->keys)) {
				$this->_selector["page"] = "auto";
			}
			if(!$this->_config->cache->fullurl && in_array("flow", $this->_config->cache->keys)) {
				$this->_selector["flow"] = "auto";
			}
		}
	}
	protected function setConfigParams() {
		$this->_allowedParams = array_merge($this->_allowedParams, $this->_config->params->allowed);
		$this->_requiredParams = array_merge($this->_requiredParams, $this->_config->params->required);

		$this->_postAllowedParams = array_merge($this->_postAllowedParams, $this->_config->post->params->allowed);
		$this->_postRequiredParams = array_merge($this->_postRequiredParams, $this->_config->post->params->required);
	}
	protected function subBuild() {
		$output = "";

		switch($this->_outputFormat) {
			case self::OutputFormatDump:
				$output = "<pre style='font-size:smaller'>";
				ob_start();
				var_dump($this->_manager->settings());
				$output .= ob_get_clean();
				$output .= "</pre>";
				break;
			case self::OutputFormatPrint:
				$output = "<pre style='font-size:smaller'>";
				$output .= print_r($this->_manager->settings(), true);
				$output .= "</pre>";
				break;
			case self::OutputFormatSerialized:
				$output = serialize($this->_manager->settings());
				break;
			case self::OutputFormatSkin:
				$output = $this->buildSkin();
				break;
			case self::OutputFormatXML:
			//$xml = new SimpleXMLElement('<root/>');
			//array_walk_recursive($this->_manager->settings(), array($xml, 'addChild'));
			//$output = $xml->asXML();
			//break;
			case self::OutputFormatJSON:
			default:
				$output = json_encode($this->_manager->settings());
				break;
		}

		return $output;
	}
	protected function subRun() {
		return true;
	}
}
